home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr49
/
actlib11.zip
/
CALC.ZIP
/
CALC.C
next >
Wrap
C/C++ Source or Header
|
1993-02-25
|
4KB
|
174 lines
/*
* Copyright (C) 1993 Marc Stern (internet: stern@mble.philips.be)
*
* CALC
*
* Topic : Mathematical expression evaluation
*
* Allowed operators : + - * / () = < > <= >= <> on floating point numbers
* % on integer numbers
*
*/
#include "calc.h"
#include <math.h>
#include <ctype.h>
#include <stdio.h>
static long double near get_expr( ) ;
static long double near fetch_operand( ) ;
static char *string ;
/*******************************************************
*
* Function : get_expr
* Topic : evaluate a mathematical expression
* Return : value of the expression or HUGE_VAL
* Input : string pointer (static variable)
* Side-effects : string will begin after expression
*
*******************************************************
*/
long double near get_expr( )
{
long double operand1 , operand2 , result = 0 ;
char operator1 = '+' , operator2 ;
for ( ; *string ; string++ )
{
operand1 = fetch_operand() ;
if ( operand1 == HUGE_VAL ) return(HUGE_VAL) ;
operator2 = *string ;
while ( (*string == '*') || (*string == '/') || (*string == '%') || (*string == '<') || (*string == '>') || (*string == '=') )
{
string++ ;
if ( *string == '=' )
switch( operator2 )
{
case '>' : operator2 = '≥' ; string++ ; break ;
case '<' : operator2 = '≤' ; string++ ; break ;
case '=' : operator2 = '=' ; string++ ; break ;
}
if ( (operator2 == '<') && (*string == '>') )
{
operator2 = '≡' ;
string++ ;
}
operand2 = fetch_operand() ;
if ( operand2 == HUGE_VAL ) return(HUGE_VAL) ;
switch( operator2 )
{
case '*' : operand1 *= operand2 ; break ;
case '/' : operand1 /= operand2 ; break ;
case '%' : operand1 = (long double) ( (int) operand1 % (int) operand2 ) ; break ;
case '=' : operand1 = (operand1 == operand2) ; break ;
case '>' : operand1 = (operand1 > operand2) ; break ;
case '≥' : operand1 = (operand1 >= operand2) ; break ;
case '<' : operand1 = (operand1 < operand2) ; break ;
case '≤' : operand1 = (operand1 <= operand2) ; break ;
case '≡' : operand1 = (operand1 != operand2) ; break ;
}
operator2 = *string ;
}
if ( operator1 == '+' ) result += operand1 ;
else result -= operand1 ;
if ( (! *string) || (operator2 == ')') ) break ;
operator1 = operator2 ;
}
return( result ) ;
}
/*******************************************************
*
* Function : fetch_operand
* Topic : fetch one operand or (...)
* Return : value of the operand or (...)
* Input : string pointer (static variable)
* Side-effects : string will begin after expression
*
*******************************************************
*/
long double near fetch_operand()
{
long double result ;
char op_str[255] , *operand ;
if ( *string == '(' ) { string++ ;
result = get_expr() ;
if ( (result == HUGE_VAL) || (*string != ')') )
return(HUGE_VAL) ; /* ) missing */
string++ ;
}
else { operand = op_str ;
if ( *string == '-' ) *operand++ = *string++ ;
while ( *string && (isdigit(*string) || (*string == '.')) )
*operand++ = *string++ ;
*operand = '\0' ;
if ( sscanf(op_str , "%Lf" , &result) != 1 )
return(HUGE_VAL) ; /* empty value or too large */
}
switch( *string ) { case '\0':
case ')' :
case '+' :
case '-' :
case '*' :
case '/' :
case '%' :
case '<' :
case '>' :
case '=' :
break ;
default : return(HUGE_VAL) ; /* Bad operator */
}
return(result) ;
}
long double calc( char *calcul )
{ long double result ;
char *ptr1 , *ptr2 ;
for ( ptr1 = ptr2 = calcul ; *ptr1 ; *ptr1++ = *ptr2++ )
while ( *ptr2== ' ' || *ptr2== '\t' ) ptr2++ ;
*ptr2 = '\0' ;
string = calcul ;
result = get_expr() ;
if ( result == HUGE_VAL ) *calcul = '\0' ;
else { /* suppress trailing '0' (and final '.') */
sprintf( calcul , "%Lf" , result ) ;
simplify( calcul ) ;
}
return(result) ;
}